// // 让字符串可以依次渲染 
// class Typing {
//     constructor(opt) {
//         // source output delay
//         const { source, output, delay } = opt;
//         this.opt = opt;
//         this.source = source;
//         this.output = output;
//         this.delay = delay || 120;
//         this.chain = {
//             parent: null,
//             dom: this.output,
//             val: []
//         }
//         if(! (typeof this.opt.done === 'function')) this.opt.done = function(){}
//     }
//     init() {
//         this.chain.val = this.convert(this.source, this.chain.val)
//     }
//     convert(dom, val) {
//         let children = Array.from(dom.childNodes)
//         for (let i = 0, l = children.length; i < l; i++) {
//             let node = children[i]
//             if(node.nodeType === 3){
//                 val = val.concat(node.nodeValue.split('')) //将字符串分割成每个字，然后依次打印
//             }else if(node.nodeType === 1){
//                 let arr = []
//                 arr = this.convert(node,arr)
//                 val.push({
//                     dom:node,
//                     val:arr
//                 })
//             }
//         }
//         return val
//     }
//     print(dom,val,callback) {
//         setTimeout(()=>{
//             dom.appendChild(document.createTextNode(val));
//             callback()
//         },this.delay)
//     }
//     play(ele) {
//         // 当打印最后一个字符时 则动画执行完毕
//         if(!ele.val.length){
//             if(ele.parent){
//                 this.play(ele.parent)
//             } else {
//                 this.opt.done()
//             }
//             return;
//         }
//         // 获取第一个元素
//         let current = ele.val.shift()
//         if(typeof current === 'string'){
//             // 调用 print 方法
//             this.print(ele.dom,current,()=>{
//                 this.play(ele) // 继续打印下一个字符
//             })
//         }else{
//             let dom = current.dom.cloneNode() //  克隆节点
//             ele.dom.appendChild(dom)
//             this.play({
//                 parent:ele,
//                 dom,
//                 val:current.val
//             })
//         }
//     }
//     start() {
//         this.init()
//         this.play(this.chain)
//     }
// }
// export default Typing

class Typing {
    constructor(opts) {
      this.opts = opts || {};
      this.source = opts.source;
      this.output = opts.output;
      this.delay = opts.delay || 120;
      this.chain = {
        parent: null,
        dom: this.output,
        val: []
      };
      if (!(typeof this.opts.done === 'function')) this.opts.done = function () {
      };
    }
  
    init() {
      //初始化函数
      this.chain.val = this.convert(this.source, this.chain.val);
    }
  
    convert(dom, arr) {
      //将dom节点的子节点转换成数组，
      let children = Array.from(dom.childNodes)
      for (let i = 0; i < children.length; i++) {
        let node = children[i]
        if (node.nodeType === 3) {
          arr = arr.concat(node.nodeValue.split(''))   //将字符串转换成字符串数组，后面打印时才会一个一个的打印
        } else if (node.nodeType === 1) {
          let val = []
          val = this.convert(node, val)
          arr.push({
            'dom': node,
            'val': val
          })
        }
      }
      return arr
    }
  
    print(dom, val, callback) {
      setTimeout(function () {
        dom.appendChild(document.createTextNode(val));
        callback();
      }, this.delay);
    }
  
    play(ele) {
      //当打印最后一个字符时，动画完毕，执行done
      if (!ele.val.length) {
        if (ele.parent) this.play(ele.parent);
        else this.opts.done();
        return;
      }
      let current = ele.val.shift()  //获取第一个元素，同时删除数组中的第一个元素
      if (typeof current === 'string') {
        this.print(ele.dom, current, () => {
          this.play(ele); //继续打印下一个字符
        })
      } else {
        let dom = current.dom.cloneNode() //克隆节点，不克隆节点的子节点，所以不用加参数true
        ele.dom.appendChild(dom)
        this.play({
          parent: ele,
          dom,
          val: current.val
        })
      }
    }
  
    start() {
      this.init();
      this.play(this.chain);
    }
  }
  
  export default Typing